#include "react.hpp"

/*
	Loads a process by its name. Window names not supported in this
	release because I'm lazy and don't feel like implementing it.
	This function is called by the second constructor.
*/
bool ReactModule::load(wchar_t* szwProcessName) {
	ProcessInfo.GetPE(szwProcessName);
	ProcessInfo.GetME(szwProcessName, ProcessInfo.pe32.th32ProcessID);
	ProcessInfo.GetPEB(ProcessInfo.pe32.th32ProcessID);

	hRead = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, false, ProcessInfo.pe32.th32ProcessID);
	hWrite = OpenProcess(PROCESS_VM_WRITE, false, ProcessInfo.pe32.th32ProcessID);
	hKill = OpenProcess(PROCESS_TERMINATE, false, ProcessInfo.pe32.th32ProcessID);

	wcscpy(wProcessName, szwProcessName);
	return attached();
}

/*
	Cleans up the process handles and Zero()s the ProcessInfoEx
	class member. Call when switching processes or before close.
	This will also Zero() the ProcessInfoEx, so you don't need
	to worry about that.
*/
bool ReactModule::unload() {
	if(hRead != INVALID_HANDLE)
		CloseHandle(hRead);
	if(hWrite != INVALID_HANDLE)
		CloseHandle(hWrite);
	if(hKill != INVALID_HANDLE)
		CloseHandle(hKill);
	ProcessInfo.Zero();
	ZeroMemory(wProcessName, 256);
	return attached();
}

/*
	Checks if all handles are valid to see if process has been opened. Note:
	not all handles may be opened, this will only return true if all are opened.
	System processes and SYSTEM_CRITICAL processes cannot get a handle with 
	PROCESS_TERMINATE permissions, so they will return false.
*/
bool ReactModule::attached() {
	return (hWrite != INVALID_HANDLE && hRead != INVALID_HANDLE && hKill != INVALID_HANDLE);
}

/*
	This will terminate the process ReactModule is attached to. It is recommended
	that if this function returns true you immediately call unload() afterwards.
	All handles and the ProcessInfoEx member will be invalid/stale.
*/
bool ReactModule::Terminate() {
	if(hKill == INVALID_HANDLE)
		return false;
	return TerminateProcess(hKill, 0);
}

/*
	Attaches a debugger, will also pause all of a process's threads.
*/
bool ReactModule::AttachDebugger() {
	return DebugActiveProcess(ProcessInfo.pe32.th32ProcessID);
}

/*
	Detaches the debugger, will also resume all of a process's threads.
*/
bool ReactModule::DetachDebugger() {
	return DebugActiveProcessStop(ProcessInfo.pe32.th32ProcessID);
}

/*
	Simply checks with the winapi function CheckRemoteDebuggerPresent() 
	to see if external process is being debugged. For self checking about
	debugging, if stealth / anti-crack / anti-debug checks are needed, instead
	get the PEB and read the BeingDebugged member from that. Most crackers
	will check for
		mov eax, fs:[30]
		add eax, 2
	which accesses the BeingDebugged member directly.
*/
mem_error ReactModule::IsBeingDebugged() {
	if(hRead == INVALID_HANDLE)
		return error;
	BOOL bDebug = false, bPEBDebug = false;
	int retVal;

	CheckRemoteDebuggerPresent(hRead, &bDebug);
	mread(ProcessInfo.pbi.PebBaseAddress->BeingDebugged, &bPEBDebug, 1);
	
	retVal = peb_results_differ + bDebug;

	if(bPEBDebug == bDebug)
		return (mem_error)bDebug;
	else return (mem_error)retVal;		// sub peb_results_differ,
}

/*
	Reads a multilevel pointer from a list of offsets, ie a cheat engine
	pointer scan list. Remember 0 is a valid offset. retAddress contains
	return. Returns true if the function was successful.
*/
bool ReactModule::pread(DWORD_PTR Address, DWORD_PTR Offsets[], BYTE numOffsets, __in PDWORD_PTR pAddress)
{
	if(hRead == NULL)
		return false;

	DWORD_PTR buffer;
	DWORD d = PAGE_EXECUTE_READWRITE, db = 0;

	for(int i = 0; i < numOffsets; i++)
	{
		buffer = NULL;
		if(!VirtualProtectEx(hRead, (LPVOID)Address, sizeof(buffer), d, &db))
			return false;
			if(!ReadProcessMemory(hRead, (LPCVOID)Address, &buffer, sizeof(buffer), NULL))
				return false;
				if(!VirtualProtectEx(hRead, (LPVOID)Address, sizeof(buffer), db, &d))
					return false;
		Address = buffer + Offsets[i];
	}

	memcpy(pAddress, (void*)Address, sizeof(DWORD_PTR));
	return true;
}

/*
	Wrapper for ReadProcessMemory and virtualprotect to read another processes
	virtual memory. Idk if it'll be needed in this class, but why not? Returns
	the number of bytes read into buffer.
*/
DWORD ReactModule::mread(DWORD_PTR Address, LPVOID buffer, DWORD size) {
	if(hRead == INVALID_HANDLE)
		return false;

	DWORD dwOldProtect = NULL, d = PAGE_EXECUTE_READ, db = 0, dwBytesRead = 0;
	if(VirtualProtectEx(hRead, (LPVOID)Address, size, d, &db))
		if(ReadProcessMemory(hRead, (LPCVOID)Address, &buffer, (SIZE_T)size, (SIZE_T*)&dwBytesRead))
			if(VirtualProtectEx(hRead, (LPVOID)Address, size, db, &d))
				return dwBytesRead;
	return 0;
}

/*
	Just a wrapper for a function to write to other process's memory. Same
	as used in trainers, was originally to write 0 to the PEB->BeingDebugged,
	however that was an unsuccessful test. Maybe there'll be a use for it. In
	the meantime, it will write to any memory where a handle for the process
	can be contained as it uses VirtualProtectEx to get page access rights.
*/
DWORD ReactModule::mwrite(DWORD_PTR Address, LPVOID buffer, DWORD size) {
	if(hWrite == INVALID_HANDLE_VALUE)
		return false;

    DWORD db = 0, d = PAGE_EXECUTE_READWRITE, dwBytesWritten = 0;
    if(VirtualProtectEx(hWrite, (LPVOID)Address, size, d, &db))								// Make sure we have readwrite access
        if(WriteProcessMemory(hWrite, (LPVOID)Address, (LPCVOID)buffer, (SIZE_T)size, (SIZE_T*)&dwBytesWritten))	// write the value
            if(VirtualProtectEx(hWrite, (LPVOID)Address, size, db, &d))						// restore old access
                return dwBytesWritten;
    return 0;
}

/*
	constructor
*/
ReactModule::ReactModule() {
	ZeroMemory(wProcessName, 256);
	hKill = INVALID_HANDLE;
	hWrite = INVALID_HANDLE;
	hRead = INVALID_HANDLE;
	ProcessInfo.Zero();
}

/*
	constructor, loads process with given name
*/
ReactModule::ReactModule(wchar_t* szwProcessName) {
	ZeroMemory(wProcessName, 256);
	hKill = INVALID_HANDLE;
	hWrite = INVALID_HANDLE;
	hRead = INVALID_HANDLE;
	ProcessInfo.Zero();
	load(szwProcessName);
}